# Create your views here.
from django.http import HttpResponse, HttpResponseRedirect
from django.utils.translation import ugettext as _
from google.appengine.api import urlfetch
from google.appengine.api import taskqueue
from django.utils import feedgenerator, simplejson
from google.appengine.ext import db

from zipbi.models import *

from collections import defaultdict

from pyExcelerator import *

import pyExcelerator

import logging, math, datetime


def sendRequestForMapp(request):
    """
    responds with the geo location
    """
    logging.info("receiving the post")
    str_position = None
    try:
        str_position = request.POST['pos']
        logging.info('pos: %s' % str_position )
    except KeyError,(strError):
        logging.error("Error: " % strError)
        return HttpResponse("Err: ver logs")

    # make the request
    url = "http://maps.googleapis.com/maps/api/geocode/json?address=";
    url = url + str_position + '&sensor=false&region=es';
    result = urlfetch.fetch(url)
    if result.status_code == 200:
        logging.info("ok - receiving")
        return HttpResponse(result.content)
    
    return HttpResponse("error")


def pocessZipCodes(request):
    """
    Process the file with all the zipcodes
    """
    blob_zipcodes = None
    
    try:
        blob_pts_ibe = request.FILES['zipCodes']
        
    except KeyError, (strErr):
        logging.error("Error saving file: %s" % strErr )
        return HttpResponse("err %s" % strErr )
    
    for line in blob_pts_ibe:
        list_values = line.split(',')
        logging.info("z: %s, prov: %s" % (list_values[0],list_values[1]) )
        if list_values[0]:
            t = taskqueue.Task(
                      url='/zipbi/processZipWorker/', 
                      params={'zipcode': list_values[0],
                              'prov': list_values[1],
                              'municipio': list_values[2],
                              }
                      
                      )
            t.add(queue_name="backgroud-proc")
    
    return HttpResponse("OK -puntos processed")

def processPuntosIbe(request):
    """
    Process the iberdrola main points. Receives two files
    """
    
    blob_pts_ibe = None
    blob_zipcodes = None
    
    try:
        blob_pts_ibe = request.FILES['ptosIber']
        
    except KeyError, (strErr):
        logging.error("Error saving file: %s" % strErr )
        return HttpResponse("err %s" % strErr )
        
    for line in blob_pts_ibe:
        list_values = line.split(',')
        if list_values[0]:
            t = taskqueue.Task(
                      url='/zipbi/processPtoWorker/', 
                      params={'zipcode': list_values[0],
                              'name':list_values[1],
                              }
                      
                      )
        
            t.add(queue_name="backgroud-proc")
        
    
    return HttpResponse("ok")


def processPtoWorker(request):
    """
    Procesamos los pts 
    """
    zip_code = None
    
    try:
        zip_code = request.POST['zipcode']
        name = request.POST['name']
    except KeyError, (strErr):
        logging.error("Error pts iber %s" % strErr )
        return HttpResponse("err %s" % strErr )
    
    pto = PuntoIberdrola.all().filter('zipcode =', zip_code).get()
    
    if not pto:
        pto = PuntoIberdrola(name=name, zipcode=zip_code)
        pto.put()
    
    logging.info("saving zipcode %s " % zip_code)
    
    # get lat and long
    url = "http://maps.googleapis.com/maps/api/geocode/json?address=";
    url = url + zip_code + '&sensor=false&region=es';
    result = urlfetch.fetch(url)
    if result.status_code == 200:
        logging.info("ok - receiving")
        logging.info("response: %s" % result.content )
        data = simplejson.loads(result.content)
        lati = None
        longi = None
        for r in data['results']:
            geometry = r['geometry']
            location = geometry['location']
            lati = location['lat'];
            longi = location['lng'];
            
        logging.info("lat: %s y long: %s" % (lati, longi) )
        pto.gpPos = db.GeoPt(lati,longi)
        pto.put()
    
    
    return HttpResponse("ok")


def processPendingPtos(request):
    """
    Procesamos los puntos pendientes
    """
    pto_list = PuntoIberdrola.all().filter('gpPos =',None).fetch(200)
    
    for pto in pto_list:
        #get the zipcode
        zip_code = pto.zipcode
        
        # now make the call
        url = "http://maps.googleapis.com/maps/api/geocode/json?address=";
        url = url + zip_code + '&sensor=false&region=es';
        result = urlfetch.fetch(url)
        if result.status_code == 200:
            logging.info("ok - receiving")
            logging.info("response: %s" % result.content )
            data = simplejson.loads(result.content)
            lati = None
            longi = None
            for r in data['results']:
                geometry = r['geometry']
                location = geometry['location']
                lati = location['lat'];
                longi = location['lng'];
            
            logging.info("lat: %s y long: %s" % (lati, longi) )
            pto.gpPos = db.GeoPt(lati,longi)
            pto.put()
    
    return HttpResponse("ptos procesadors")

def processZipWorker(request):
    """
    Procesamos los zipcodes y asignamos el lat y long
    """
    zip_code = None
    provincia = None
    municipio = None
    
    try:
        zip_code = request.POST['zipcode']
        provincia = request.POST['prov']
        municipio  = request.POST['municipio']
    except KeyError, (strErr):
        logging.error("Error pts iber %s" % strErr )
        
    
    # sanity check
    
    zip_code_obj = ZipCode.all().filter('zipcode =',zip_code).get()
    
    if not zip_code_obj:
        zip_code_obj = ZipCode(zipcode=zip_code,
                           provincia=provincia,
                           municipio=municipio)
    
        zip_code_obj.put()
        
    logging.info("saved zip code")
    
    if zip_code_obj.gpPos:
        return HttpResponse("ya lo tenemos asignado")
    
    # get lat and long
    url = "http://maps.googleapis.com/maps/api/geocode/json?address=";
    url = url + zip_code + '&sensor=false&region=es';
    result = urlfetch.fetch(url)
    if result.status_code == 200:
        logging.info("ok - receiving")
        logging.info("response: %s" % result.content )
        data = simplejson.loads(result.content)
        lati = None
        longi = None
        for r in data['results']:
            geometry = r['geometry']
            location = geometry['location']
            lati = location['lat'];
            longi = location['lng'];
            
        logging.info("lat: %s y long: %s" % (lati, longi) )
        zip_code_obj.gpPos = db.GeoPt(lati,longi)
        zip_code_obj.audit_dt_updated = datetime.datetime.now()
        zip_code_obj.put()
    
    
    return HttpResponse("OK")

def calculateDistances(request):
    """
    Calculates the different disntaces comparing each
    zipcode to all the puntos iberdrola
    """
    
    logging.info("iniciamos la peticion")
    
    # obtenemos la lista de todos 
    query = ZipCode.all()
    query.filter('gpPos !=',None)
    
    # la lista total aqui
    list_zip_codes = query.fetch(1500)
    
    # now for all the zipcodes send them to calculate the dist
    
    for zip in list_zip_codes:
        # send to calculate
        t = taskqueue.Task(
                      url='/zipbi/processZipDist/', 
                      params={'zipcodekey': zip.key(),
                              }
                      )
        
        t.add(queue_name="geo-backgroud-proc") 
    
    return HttpResponse("OK - Todos los puntos enviados")

def processZipDist(request):
    """
    Procesando las distancias entre zipcodes
    """
    
    zip_key = None
    
    try:
        zip_key = request.POST['zipcodekey']
        logging.info("zip source: %s" % zip_key)
    except KeyError, (strError):
        logging.info("Error: %s" % strError)
        
    zip_code_obj = db.get(zip_key)
    
    # ahora obtenemos las listas de puntos iberdrola
    
    list_pts_iberdrola = PuntoIberdrola.all().fetch(100)
    
    #http://maps.googleapis.com/maps/api/directions/json?origin=08013&destination=08630&region=es&sensor=false
    
    # ahora procesamos las distancias
    url = "http://maps.googleapis.com/maps/api/directions/json?origin=";
    
    for pto in list_pts_iberdrola:
        logging.info("processing pto : %s" % pto.zipcode )
        
        other_dist = returnDistance(zip_code_obj.gpPos, pto.gpPos)
        
        dist = Distances(distance=int(other_dist),
                         pto_iberdrola=pto.zipcode,
                         zipcode=zip_code_obj)
        dist.put()
        logging.info("saving distances")
    
    
    # now assign them
    shortest_distance = zip_code_obj.distances.order('distance').get()
    zip_code_obj.assigned_pto = shortest_distance.pto_iberdrola
    zip_code_obj.put()
    logging.info("pto assigned")
        
#        burl = url + zip_code_obj.zipcode + '&destination=%s&region=es&sensor=false' % (pto.zipcode);
#        logging.info("ulr: %s" % burl)
#        result = urlfetch.fetch(burl)
#        if result.status_code == 200:
#            data = simplejson.loads(result.content)
#            logging.info("info html: %s" % data['status'])
            
#            int_total_value = 0
#            for r in data['routes']:
#                for l in r['legs']:
#                    distance = l['distance']
#                    int_total_value = int(distance['value'])
#                    logging.info("distance: %d and %d" % (int_total_value, other_dist) )
            
       
            
    return HttpResponse("OK")




def returnDistance(gpPosSource,gpPosDest):
    """
    calculates the result of the two points
    """
    logging.info("receiving all doubles")
    
    lat1 = gpPosSource.lat
    lon1 = gpPosSource.lon
    
    lat2 = gpPosDest.lat
    lon2 = gpPosDest.lon
    
    dLat = math.radians(lat2 - lat1)
    dLon = math.radians(lon2 - lon1)
    
    a = math.sin(dLat / 2) * math.sin(dLat / 2) + \
          math.cos(  math.radians(lat1) ) * math.cos( math.radians(lat2) ) *  \
          math.sin(dLon / 2) * math.sin(dLon / 2) 
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) 
    d = 6371 * c
    return d


def generateExcelReport(request):
    """
    Generates a list of the report for the assignments
    """
    
    logging.info("receiving report request")
    
    str_zipcode = None
    
    try:
        str_zipcode = request.POST['zipcode']
        # esperamos un zipcode
    except KeyError, (strError):
        logging.info("Error: %s" % strError)
        
    # receive assigned zipcodes
    
    pto_iberdrola = PuntoIberdrola.all().filter('zipcode =',str_zipcode).get()
    
    list_assigned = ZipCode.all().filter('assigned_pto =', str_zipcode).fetch(1000)
    
    # create spreadsheet
    wb = Workbook()
    ws0 = wb.add_sheet('ptosIberdrola')
    
    for y in range(0, len(list_assigned) ):
        ws0.write(y, 0, "%s" % list_assigned[y].zipcode )
        ws0.write(y, 1, "%s" % list_assigned[y].provincia )
        ws0.write(y, 2, "%s" % list_assigned[y].municipio )
            
    response = HttpResponse(mimetype="application/ms-excel")
    response['Content-Disposition'] = 'attachment; filename=file_%s.xls' % pto_iberdrola.name

    wb.save(response)
    
    return response

def read_excel(request):
    """
    Reads from an excel file
    """
    blob_pts_ibe = None
    
    try:
        blob_pts_ibe = request.FILES['zipCodes']
    except KeyError,(strError):
        logging.error("Error: %s"% strError)
    
    logging.info("reading the file")
    book = pyExcelerator.parse_xls(blob_pts_ibe)
    
    logging.info("obtenemos el sheet")
    data = book[0][1]

    # ahora procesamos cada fila
    parsed_dictionary = defaultdict(lambda: None, book[0][1])
    
    # number of columns
    number_of_rows = len(parsed_dictionary)/3
    
    for i in range(0,number_of_rows):
        # si existe
        if parsed_dictionary[i,0]:
            logging.info("zip code: %s municipi: %s" % (parsed_dictionary[i,0], parsed_dictionary[i,2]) )
            t = taskqueue.Task(
                      url='/zipbi/processZipWorker/', 
                      params={'zipcode': parsed_dictionary[i,0],
                              'prov': parsed_dictionary[i,1],
                              'municipio': parsed_dictionary[i,2],
                              }
                      
                      )
            t.add(queue_name="backgroud-proc")

    return HttpResponse("OK")

def cleanupMessWorker(request):
    """
    Basic cleanup para las tareas aquellas que quedaron colgadas
    Intended to be run as a task
    """
    
    # obtenemos la lista de todos ZipCode.all()  #
    query = db.Query(ZipCode, keys_only=True) 
    query.filter('gpPos =',None)
    
    # la lista total aqui
    list_zip_codes = query.fetch(3000)

    # delet all the bastards
    try:
        db.delete( list_zip_codes )
    except db.Error, (strError):
        logging.error("Error borrando: %s" % strError)    
    
    return HttpResponse("OK")

